package com.wealth.wechat.service;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.wealth.order.entity.Order;
import com.wealth.order.entity.OrderPlat;
import com.wealth.payment.entity.PaymentAccount;
import com.wealth.platform.entity.SldConfig;
import com.wealth.wechat.entity.WechatConfig;
import com.wealth.wechat.util.MD5Util;
import com.wealth.wechat.util.TrustSSL;
import com.wealth.wechat.util.XmlParser;

@Service
public class WechatPayService{
	
	Logger logger = Logger.getLogger(WechatPayService.class);
	
	/** 微信支付统一下单地址
	 * 微信支付帮助库
	 * ====================================================
	 * 接口分三种类型：
	 * 【请求型接口】--Wxpay_client_
	 * 		统一支付接口类--UnifiedOrder
	 * 		订单查询接口--OrderQuery
	 * 		退款申请接口--Refund
	 * 		退款查询接口--RefundQuery
	 * 		对账单接口--DownloadBill
	 * 		短链接转换接口--ShortUrl
	 * 【响应型接口】--Wxpay_server_
	 * 		通用通知接口--Notify
	 * 		Native支付——请求商家获取商品信息接口--NativeCall
	 * 【其他】
	 * 		静态链接二维码--NativeLink
	 * 		JSAPI支付--JsApi
	*/
	public static final String WXPAY_UNIFIEDORDER= "https://api.mch.weixin.qq.com/pay/unifiedorder";
	
	/**
	 * 获取支付参数
	 * @param tcorp
	 * @param order
	 * @param payaccount
	 * @return
	 * @throws Exception 
	 */
	public JSONObject getPayParam(WechatConfig wechatConfig,SldConfig sldConfig,PaymentAccount payaccount,
			OrderPlat orderPlat,String openid,HttpServletRequest request) throws Exception{
		
		//公众账号ID
		String appid = wechatConfig.getWxappid();
		//商户号
		String mch_id = payaccount.getPartnerid();
		//随机字符串
		String nonce_str=getRandomString(12);
		
		StringBuffer sb=new StringBuffer();
		//商品或支付单简要描述
		for (Order order : orderPlat.getOrderList()) {
			for (int i = 0; i < order.getOrderItemList().size(); i++) {
				sb.append(order.getOrderItemList().get(i).getGoods().getName());
				if(i+1 !=order.getOrderItemList().size()){
					sb.append(",");
				}
			}
		}
		String body = sb.toString();
		String out_trade_no=orderPlat.getOrderno();
		//订单总金额(以一分钱为单位)，只能为整数
		Double d = orderPlat.getTotal()*100;
		String total_fee =String.valueOf(d.intValue()); 
		//终端IP
		String spbill_create_ip= request.getRemoteAddr();
		//通知地址
		String notify_url=sldConfig.getDomain()+"/pay/notify_url/"+orderPlat.getCorp().getId()+"/"+orderPlat.getId();
		//交易类型
		String trade_type = "JSAPI";

		//用户标识 openid;
		
		//生成商品包信息
		SortedMap<String, String> packageParams = new TreeMap<String, String>();
		packageParams.put("appid", appid); 
		packageParams.put("mch_id",mch_id); 	  
		packageParams.put("nonce_str", nonce_str);  
		packageParams.put("body", body); 
		packageParams.put("out_trade_no", out_trade_no);
		packageParams.put("total_fee", total_fee);
		packageParams.put("spbill_create_ip", spbill_create_ip);
		packageParams.put("notify_url", notify_url);
		packageParams.put("trade_type", trade_type);
		packageParams.put("openid", openid);
		
		//统一支付接口签名
		String packageValue = MD5Util.createSignAddKey(packageParams,payaccount.getPayservice());
		packageParams.put("sign", packageValue);
		
		Map<String, Object> map_result = new HashMap<String, Object>();
		map_result.putAll(packageParams);
		String xmlSting =XmlParser.map2XmlStr(map_result,"XML");
		
		//统一支付接口  请求
		String jsonStr = TrustSSL.sendNewRequest(WXPAY_UNIFIEDORDER, xmlSting);
		map_result=XmlParser.xmlStr2Map(jsonStr);
		//错误code
		map_result.put("errcode","00");
		//统一支付接口调用成功
		if(map_result!=null && map_result.get("return_code").equals("SUCCESS")){
			//微信生成的预支付成功
			if(map_result.get("result_code").equals("SUCCESS")){
				map_result.put("errcode","01");
				
				//生成JSAPI 参数返回给H5端
				SortedMap<String, String> map_JSAPI = new TreeMap<String, String>();
				map_JSAPI.put("appId",appid);
				map_JSAPI.put("timeStamp",create_timestamp());
				map_JSAPI.put("nonceStr",nonce_str);
				map_JSAPI.put("package","prepay_id="+map_result.get("prepay_id"));
				map_JSAPI.put("signType","MD5");
				//JSAPI签名
				String paySign = MD5Util.createSignAddKey(map_JSAPI,payaccount.getPayservice());
				map_JSAPI.put("paySign",paySign);
				//抽奖业务逻辑，不能放到上面，导致签名错误
				map_JSAPI.put("total", orderPlat.getTotal().toString());
				
				//返回参数
				map_result.putAll(map_JSAPI);
				
			}
			//微信生成的预支付  失败
			else{
				//返回错误描述
				map_result.put("return_msg",map_result.get("err_code_des"));
			}
		}
		
		//处理返回  JSAPI 参数
		JSONObject result =JSONObject.parseObject(JSON.toJSONString(map_result));
		logger.info("统一支付接口jsonStr="+result);

		return result;
	}
	
	/**
	 * 生成订单号
	 * @param shopid
	 * @return
	 */
	public String getTradeno(Long shopid){
		String randomStr = this.getRandomString(8);
		long t = new Date().getTime();
		String tradeNo = Long.toString(shopid)+Long.toString(t)+randomStr;
		return tradeNo;
	}
	
	/**
	 * 生成随机字符串
	 * @param length
	 * @return
	 */
	private  String getRandomString(int length) { //length表示生成字符串的长度
	    String base = "abcdefghijklmnopqrstuvwxyz0123456789";   
	    Random random = new Random();   
	    StringBuffer sb = new StringBuffer();   
	    for (int i = 0; i < length; i++) {   
	        int number = random.nextInt(base.length());   
	        sb.append(base.charAt(number));   
	    }   
	    return sb.toString();   
	 }
	
	/**
	 * 当前的时间
	 * */
    private String create_timestamp() {
        return Long.toString(System.currentTimeMillis() / 1000);
    }
	
	/**
	 * 从输入流读取post参数
	 * @param in
	 * @return
	 */
	public String readStreamParameter(ServletInputStream in){
		StringBuilder buffer = new StringBuilder();
		BufferedReader reader=null;
		try{
			reader = new BufferedReader(new InputStreamReader(in));
			String line=null;
			while((line = reader.readLine())!=null){
				buffer.append(line);
	        }
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if(null!=reader){
				try {
					reader.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return buffer.toString();
	}
    
	/**
	 * 发送流
	 * @param response
	 * @param sendstr
	 */
	public void sendStream(HttpServletResponse response, String sendstr){
		try{
			OutputStream os = response.getOutputStream();
			os.write(sendstr.getBytes());
			os.flush();
			os.close();
		}catch(Exception e){
			e.printStackTrace();
		}
	}
}
